package multiplayerShooter;

import imageLoader.ImageLoader;

import java.awt.Graphics;
import java.awt.Image;
import java.util.Iterator;
import java.util.List;

public class Player implements Printable{
	
	
	static Image[][] img = new Image[2][5];//img[Direction][movement]
	static Image playerDead;//Image used when health is 0 could be added to above^
	public static int defaultRespawnTime = 1000;
	
	enum Direction {LEFT(0), RIGHT(1);	
		private int value;
		private Direction(int val){value = val;}		
		public int getValue(){return value;}
	}
	
	final int minXpos;
	final int maxXpos;
	
	
	private int xPos = 500;
	public int getXPos() {
		return xPos;
	}



	public void setXPos(int pos) {
		xPos = pos;
	}



	int yPos = 600;
	

	private Direction direction = Direction.LEFT;
	private int movement = 0;
	private int health = 10;
	
		

	private Printer printer;
	private List<Player> allPlayers;	
	private List<Block> blocks;
	private Thread respawnThread;
	
	
	
	private boolean continueMovingLeft;
	private boolean continueMovingRight;
	private boolean continueJumping;
	private boolean continueShooting;

	
	
	
	
	static{
		loadImages();		
	}
	
	
	
	public Player(Printer printer_,List<Player> players_,List<Block> blocks_) {
		this.allPlayers=players_;
		this.printer = printer_;
		this.blocks = blocks_;
		if(!allPlayers.contains(this))
			allPlayers.add(this);
		if(printer!=null)
		{
			minXpos = printer.getMinX();
			maxXpos = printer.getMaxX()-77;
		}
		else
		{
			minXpos = 0;
			maxXpos = 1024-77;
		}
			
		Thread gravityThread = new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(5);
					} catch (Exception e) {
					}
					if (onGround(Player.this.xPos + 37, Player.this.yPos + 84));
					else if (onGround(Player.this.xPos + 37, Player.this.yPos + 85))
						Player.this.yPos += 1;					
					else					
						Player.this.yPos += 2;
				//TODO Flawed Must Have "Grounds" pull player instead (so blocks moving up and down always work)		
						//Or something else :-p

				}

			}
		};
		gravityThread.start();
	}

	

	
	public List<Player> getAllPlayers() {
		return allPlayers;
	}
	public void paintPlayer(Graphics graph) {

		if (this.getHealth() > 0)
			graph.drawImage(img[getDirection().getValue()][this.movement], this.xPos, this.yPos,
					null);
		else
			graph.drawImage(playerDead, this.xPos, this.yPos, null);
	}

	public void startMoveingLeft() {

		if (!this.continueMovingLeft) {
			this.continueMovingLeft = true;
			this.continueMovingRight = false;

			Thread leftThread = new Thread() {
				public void run() {

					while (Player.this.continueMovingLeft && Player.this.getHealth() > 0) {
						stepLeft();
						try {Thread.sleep(35);}catch (Exception e) {}

					}

				}
			};
			leftThread.start();
		}

	}
	public void stopMovingLeft()
	{
		continueMovingLeft = false;
	}
	public void startMovingRight() {
		if (!this.continueMovingRight) {
			this.continueMovingRight = true;
			this.continueMovingLeft = false;

			Thread rightThread = new Thread() {
				public void run() {

					while (Player.this.continueMovingRight && Player.this.getHealth() > 0) {
						stepRight();
						try {
							Thread.sleep(35);
						} catch (Exception e) {
						}
					}

				}
			};
			rightThread.start();
		}

	}
	public void stopMovingRight()
	{
		continueMovingRight = false;
	}
	public void stopJumping(){continueJumping=false;}
	public void startJumping() {
				
		if(continueJumping!=true)
		{
			continueJumping=true;
			Thread jumpThread = new Thread() {
				public void run() {
					while(continueJumping)
					{
						if (onGround(xPos + 37, yPos + 84) && getHealth() > 0)
						{
							int lastMovement = movement;
							movement = 4;
		
							for (int d = 0; d <= 30; d++) {
								try {
									Thread.sleep(5);
								} catch (Exception e) {
								}
								yPos -= 6;
							}
							movement = lastMovement;
						}
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					
				}
			};
			jumpThread.start();
		}		
	}

	public void down() {
		if (this.yPos < 600 && onGround(this.xPos + 37, this.yPos + 84))
			this.yPos += 5;
	}

	public void startShooting() {
		final Player theKiller = this;
		if (!this.continueShooting && this.getHealth() > 0) {
			this.continueShooting = true;

			Thread shootThread = new Thread() {
				public void run() {

					while (Player.this.continueShooting) {
						Bullet b = new Bullet(theKiller);
						printer.addPrintableObject(b);
						b.fire();

						try {
							Thread.sleep(150);
						} catch (Exception e) {
						}
					}

				}
			};
			shootThread.start();
		}
	}
	public void stopShooting()
	{
		this.continueShooting = false;
	}
	

	public boolean onGround(int x_, int y_) {
		Iterator<Block> it = this.blocks.iterator();

		if (y_ == 600 + 84)
			return true;
		while (it.hasNext()) {
			Block current = (Block) it.next();
			
			if (current.onBlock(x_, y_, this))
				return true;
			if(current instanceof MovingBlock){
				if(((MovingBlock)current).playersOnBlock.contains(this)){
				return true;
				}
			}
		} // end while

		return false;

	}

	
	
	public boolean stepLeft(){	
		this.setDirection(Direction.LEFT);
		if(xPos!=minXpos)
		{
			updateMovement();
			if(xPos-8>=minXpos )
				this.xPos-=8;
			else
				xPos=minXpos;
			
			return true;
		}
		else
			return false;
	
	}
	public boolean stepLeft(int steps){	
		for(;steps>0;steps--){		
			if(!stepLeft())
				return false;
		}
		
		return true;
	}
	public boolean stepRight(int steps){	
		for(;steps>0;steps--){		
			if(!stepRight())
				return false;
		}		
		return true;
	}
	public boolean stepRight(){
		this.setDirection(Direction.RIGHT);
		if(xPos!=maxXpos)
		{
			updateMovement();
			if(xPos+8<=maxXpos )
				this.xPos+=8;
			else
				xPos=maxXpos;
			return true;
		}
		else
			return false;
		
	}
	private void updateMovement(){
		if (onGround(Player.this.xPos + 37, Player.this.yPos + 84)) {
			Player.this.movement++;
			Player.this.movement %= 2;
		}
	}
	public void decreaseHealthByPercent(int percent){
		setHealth(getHealth() - (percent/10));
	}
	public Thread respawn(final int milliseconds){
		if(getHealth()==0 && (respawnThread==null || !respawnThread.isAlive()))
		{			
			respawnThread = new Thread(){
				public void run()
				{
					try {
						Thread.sleep(milliseconds);
					} catch (InterruptedException e) {
					
						e.printStackTrace();
					}
					setHealth(10);
				}
			};
			respawnThread.start();
		}
		return respawnThread;		
	}
	
	public Thread respawn(){
		return respawn(defaultRespawnTime);		
	}

	public void draw(Graphics g) {
	if (this.getHealth() > 0)
		g.drawImage(img[getDirection().getValue()][this.movement], this.xPos, this.yPos,
				null);
	else
		g.drawImage(playerDead, this.xPos, this.yPos, null);
		
	}

	public boolean printItem() {
		return true;		
	}

	public boolean isDead() {
		return this.getHealth()==0;
	}
	
	private static void loadImages()
	{
		img[0][0] = ImageLoader.getImage("PlayerLeft2.gif");
		img[0][1] = ImageLoader.getImage("PlayerLeft1.gif");
		img[1][0] = ImageLoader.getImage("PlayerRight2.gif");
		img[1][1] = ImageLoader.getImage("PlayerRight1.gif");
		img[0][4] = ImageLoader.getImage("PlayerLeftJump.gif");
		img[1][4] = ImageLoader.getImage("PlayerRightJump.gif");
		playerDead = ImageLoader.getImage("PlayerDead.gif");
	}



	public void setDirection(Direction direction) {
		this.direction = direction;
	}

	public Direction getDirection() {
		return direction;
	}

	public void setHealth(int health) {
		this.health = health;
	}



	public int getHealth() {
		return health;
	}



	
}